/*
     Copyright 2007 Joseph M. Ferner

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.IO;
using OpenServers.Net.Common.Utils;

namespace OpenServers.Net.Common.FileSystem.Disk {
    /// <summary>
    /// a file backed by disk representing a file on disk.
    /// </summary>
    public class DiskFile : DiskFileSystemObject<FileInfo>, IFile {
        /// <summary>
        /// constructor.
        /// </summary>
        /// <param name="parent">The parent directory</param>
        /// <param name="path">The path to the file.</param>
        public DiskFile(IDirectory parent, string path)
            : base(parent, new FileInfo(path)) {
        }

        /// <summary>
        /// constructor.
        /// </summary>
        /// <param name="parent">The parent directory</param>
        /// <param name="fileInfo">The file info for the file</param>
        public DiskFile(IDirectory parent, FileInfo fileInfo)
            : base(parent, fileInfo) {
        }

        /// <summary>
        /// open an input stream.
        /// </summary>
        public Stream OpenInputStream() {
            return FileSystemInfo.OpenRead();
        }

        /// <summary>
        /// open an output stream.
        /// </summary>
        public Stream OpenOutputStream() {
            File.WriteAllBytes(FileSystemInfo.FullName, new byte[] { });
            return FileSystemInfo.OpenWrite();
        }

        /// <summary>
        /// Gets the size of a file object.
        /// </summary>
        public long Size {
            get { return FileSystemInfo.Length; }
        }

        /// <summary>
        /// moves the object to another location.
        /// </summary>
        /// <param name="fso"></param>
        public override void MoveTo(IFileSystemObject fso) {
            if (fso is IFile) {
                IFile newFile = (IFile)fso;
                Stream output = null;
                Stream input = null;
                try {
                    output = newFile.OpenOutputStream();
                    input = OpenInputStream();

                    StreamUtils.Copy(input, output);
                } finally {
                    if (output != null) {
                        output.Close();
                    }
                    if (input != null) {
                        input.Close();
                    }
                }
                Delete();
            } else if (fso is IDirectory) {
                IDirectory newDir = (IDirectory)fso;
                IFile newFile = newDir.CreateFile(Name);
                MoveTo(newFile);
            } else {
                throw new ApplicationException("Invalid file system object type");
            }
        }
    }
}
